iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
自我挑戰組

Ruby OOP to Oops !n 30系列 第 14

IT 邦鐵人賽 Day 14 - Singleton

  • 分享至 

  • xImage
  •  

單例模式(Singleton)

目的:

確保類別只會有一個物件實體存在,並提供單一存取窗口

結構:

單例模式(Singleton)只有一個類別,來控管物件的產生
並且定義一個方法作為介面,來讓外界經由此介面來存取唯一個體
但唯一可能出現問題的,會是Race Condition
多執行緒的競爭關係,會導致實體重複產生

程式碼範例:

不考量Race Condition

class Singleton
  @instance = new

  private_class_method :new

  def self.instance
    @instance ||= Singleton.new
  end

  def some_business_logic
    # do something
  end
end

s1 = Singleton.instance
s2 = Singleton.instance

if s1.equal?(s2)
  print 'Singleton works, both variables contain the same instance.'
else
  print 'Singleton failed, variables contain different instances.'
end

結果

Singleton works, both variables contain the same instance.

解釋

由於只要產生一個物件,所以不把new作為公共介面使用
而是在instance中判定是否有已經存在的物件存在@instance
若是沒有則new出實體後存入,有的話直接取用@instance即可

考量Race Condition

class Singleton
  attr_reader :value

  @instance_mutex = Mutex.new

  private_class_method :new

  def initialize(value)
    @value = value
  end

  def self.instance(value)
    return @instance if @instance

    @instance_mutex.synchronize do
      @instance ||= new(value)
    end

    @instance
  end

  def some_business_logic
    # do something
  end
end

def test_singleton(value)
  singleton = Singleton.instance(value)
  puts singleton.value
end


puts "If you see the same value, then singleton was reused (yay!)\n"\
     "If you see different values, then 2 singletons were created (booo!!)\n\n"\
     "RESULT:\n\n"

process1 = Thread.new { test_singleton('FOO') }
process2 = Thread.new { test_singleton('BAR') }
process1.join
process2.join

結果

FOO
FOO

解釋

這裡使用的Mutex就是讓我們自設計一個GIL(Global Interpreter Lock)
當兩個執行序進行時,使用synchronize確保一個執行序完成後,再執行下一個
而由於已經產生了物件,另一個執行緒就無法再次生成

(當然這種做法有一個風險,那就是造成Deadlock

優點

  1. 單例模式(Singleton)的使用可以將生成的個體封裝起來,意味著掌控存取方式與時機
    換句話說,若是使用全域變數,就需要在一開始時產生(不管會不會用到),而此模式可以自由調控
  2. 因為Singleton類別是可以被繼承的,所以增加使用彈性
  3. 其實單例模式(Singleton)並非只能產生一個物件,而是可以將程式碼修改成需要幾個就幾個

文章不定期更新!

感謝大家 如有問題,再煩請大家指教!


上一篇
IT 邦鐵人賽 Day 13 - Prototype
下一篇
IT 邦鐵人賽 Day 15 - Adapter
系列文
Ruby OOP to Oops !n 3020
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Jean_HSU
iT邦新手 5 級 ‧ 2022-10-03 22:02:18

喳喳

我要留言

立即登入留言